package de.schiess.main;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.logging.Logger;

import model.Bot;
import model.Card;
import model.Pricedata;
import model.PricedataHasBot;
import model.PricedataHasBotId;
import model.Vendor;

import de.schiess.hbt2.db.DBConnector;
import de.schiess.util.CardConstants;

public class SupernovaCardExtractor implements ICardExtractor {
	ArrayList<Card> cardList = null;
	HashMap<String, Card> cardMap = null;
	Vendor vendor = null;
	final static String SUPERNOVA = "Supernova";
	private static Logger logger = Logger.getAnonymousLogger();

	public SupernovaCardExtractor() {

		Vendor dbVendor = Vendor.getByName(SUPERNOVA);
		if (dbVendor != null) {
			vendor = dbVendor;
		} else {
			createSupernovaVendor();
			vendor.save();
		}
	}

	private void createSupernovaVendor() {
		vendor = new Vendor();
		vendor.setCrawlerClass(SuperNovaCrawler.class.toString());
		vendor.setPathToPrices("http://supernovabots.com/prices_0.txt");
		vendor.setName("Supernova");
		vendor.setWebsite("http://supernovabots.com/");
	}

	@Override
	public ArrayList<Card> getCards() {
		return null;
	}

	@Override
	public HashMap<String, Card> getCardsAsMap() {

		if (this.cardMap == null) {
			ArrayList<Card> list = this.getCards();
			HashMap<String, Card> out = new HashMap<String, Card>();
			for (Card card : list) {
				out.put(card.getName() + "[" + card.getEdition() + "]", card);
			}
			return out;
		} else {
			return this.cardMap;
		}
	}

	@Override
	public ArrayList<Card> getAllVersions(String cardname) {
		ArrayList<Card> out = new ArrayList<Card>();
		for (Card card : this.getCards()) {
			if (card.getName().toLowerCase().contains(cardname.toLowerCase())) {
				out.add(card);
			}
		}
		return out;
	}

	@Override
	public ArrayList<Card> getCards(Date date) {
		ArrayList<String> list = new ArrayList<String>();
		try {
			PriceFile.get();
			FileInputStream fstream = new FileInputStream("prices_0.txt");
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine;
			while ((strLine = br.readLine()) != null) {
				list.add(strLine);
			}
			in.close();
		} catch (Exception e) {
			System.err.println("Error: " + e.getMessage());
		}

		ArrayList<String> lines = list;
		ArrayList<Card> out = new ArrayList<Card>();
		for (int i = 9; i < lines.size(); i++) {
			boolean log = (i % 100 == 0);
			if(log)logger.info("============================New Cycle=====================");
			if(log)logger.info("currently at Line " + i + " / " + lines.size());
			if (lines.get(i).length() > 2 && !lines.get(i).startsWith("=")) {
				Date start = null;
				Date end = null;
				Card card = null;
				start = new Date();
				String line = lines.get(i);
				String cardName = line.substring(0, 51).trim()
						.replace("'", "#");
				int oBracket = cardName.indexOf("[");
				int cBracket = cardName.indexOf("]");
				String set = cardName.substring(oBracket + 1, cBracket);
				String name = cardName.substring(0, oBracket - 1);
				end = new Date();
				if(log)logger.info("Extracting basic cardinfo took "+(end.getTime()-start.getTime())+" ms");
				start = new Date();
				// querying DB if Card exists
				card = Card.get(name, set, CardConstants.RARE,
						CardConstants.NORMAL);
				end = new Date();
				if(log)logger.info("Querying DB if card exists took "+(end.getTime()-start.getTime())+" ms");
				start = new Date();
				if (card == null) {
					// Building basic Card attributes
					card = new Card();
					card.setName(name);
					card.setEdition(set);
					card.setRarity(CardConstants.RARE);
					card.setFoil(CardConstants.NORMAL);
					// Done building basic Card attributes
					card.save();
					end = new Date();
					if(log)logger.info("Saving new card took "+(end.getTime()-start.getTime())+" ms");
				}
				// end

				Pricedata pd = new Pricedata();
				pd.setCard(card);
				pd.setDate(date.getTime());
				pd.setVendor(vendor);
				start = new Date();
				// extracting buyprice
				String price = line.substring(51, 61).trim();
				int buyPrice = 0;
				if (price != null && !price.isEmpty()) {
					try {
						buyPrice = (int) Math
								.round(Double.parseDouble(price) * 100);
					} catch (NumberFormatException e) {
						e.printStackTrace();
						break;
					}
				}
				pd.setBuyPrice(buyPrice);
				end = new Date();
				if(log)logger.info("Extracting buyprice took "+(end.getTime()-start.getTime())+" ms");
				// Done extracting buyprice
				start = new Date();
				// extracting sellprice
				price = line.substring(61, 71).trim();
				int sellPrice = 0;
				if (price != null && !price.isEmpty()) {
					try {
						sellPrice = (int) Math
								.round(Double.parseDouble(price) * 100);
					} catch (NumberFormatException e) {
						e.printStackTrace();
						break;
					}
				}
				pd.setSellPrice(sellPrice);
				// Done extracting sellprice
				end = new Date();
				if(log)logger.info("Extracting sellprice took "+(end.getTime()-start.getTime())+" ms");
				start = new Date();
				pd.save();
				end = new Date();
				if(log)logger.info("Saving Pricedata took "+(end.getTime()-start.getTime())+" ms");
				start = new Date();
				// Building Bot availability
				String avail = line.substring(71).trim();
				String[] bots = avail.split(" ");
				for (String bot : bots) {

					if (bot != null && !bot.isEmpty()) {
						oBracket = bot.indexOf("[");
						cBracket = bot.indexOf("]");
						String botAvail = bot.substring(oBracket + 1, cBracket);
						String botName = bot.substring(0, oBracket);
						end = new Date();
						if(log)logger.info("Extracting botavailability took "+(end.getTime()-start.getTime())+" ms");
						start = new Date();
						// checking for bot in db
						Bot b = Bot.get(botName, vendor.getIdVendor());
						end = new Date();
						if(log)logger.info("Checking if bot exists took "+(end.getTime()-start.getTime())+" ms");
						if (b == null) {
							start = new Date();
							b = new Bot();
							b.setName(botName);
							b.setVendor(vendor);
							b.save();
							end = new Date();
							if(log)logger.info("Saving Bot took "+(end.getTime()-start.getTime())+" ms");
						}
						// end checking for bot in db
						start = new Date();
						PricedataHasBot pdHasBot = new PricedataHasBot();
						try {
							// checking for availability
							pdHasBot.setBot(b);
							pdHasBot.setPricedata(pd);
							PricedataHasBotId pid = new PricedataHasBotId();
							pid.setBotIdBot(b.getIdBot());
							pid.setPriceDataIdPriceData(pd.getIdPriceData());
							pdHasBot.setId(pid);
							pdHasBot.save();
							// emd checking for availability
							int x = Integer.parseInt(botAvail);
							pdHasBot.setQuantity(x);
						} catch (NumberFormatException e) {
							pdHasBot.setQuantity(0);
						} finally {
							pd.save();
						}
						end = new Date();
						if(log)logger.info("Saving PricedataHasBot took "+(end.getTime()-start.getTime())+" ms");
					}

				}
				// Done building Bot availability

			}
		}
		this.cardList = out;
		DBConnector.close();
		return out;
	}

}
